﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WebApp.Code;
using System.Security.Principal;
using System.Text;
using System.IO;
using WindowsSignInPage;

namespace WebApp.Controls
{
    public partial class DiskManager : System.Web.UI.UserControl, ICallbackEventHandler, IPostBackEventHandler
    {
        Profile userProfile;

        public string Domain
        {
            get
            {
                return "ceibs.edu";
            }
        }
        public NetDrive CurrentDrive
        {
            get { return ViewState["CurrentDrive"] as NetDrive; }
            set { ViewState["CurrentDrive"] = value; }
        }
        public string CurrentPath
        {
            get
            {
                //return UploadContext.GetUploadFolder();
                return Cache[UserName] as string; 
            }
            set
            {
                //UploadContext.InitUploadFolder(value);
                Cache[UserName] = value; 
            }
        }
        private EventName callbackEvent { get; set; }

#if !DEBUG
        public string UserName
        {
            get
            {
                return "leon";
            }
        }
        public string Password
        {
            get
            {
                return "leon@123";
            }
        }
        //public string DirectoryRoot 
        //{
        //    get { return ViewState["DirectoryRoot"] as string; }
        //    set { ViewState["DirectoryRoot"] = value; }
        //}
        //public string DriveName
        //{
        //    get { return ViewState["DriveName"] as string; }
        //    set { ViewState["DriveName"] = value; }
        //}

        protected override void OnInit(EventArgs e)
        {
            try
            {
                userProfile = new Profile();
                string drive1 = @"\\MOSS2010\Upload";
                userProfile.NetDrives.Add(new NetDrive("Z", drive1));

            }
            catch (Exception ex)
            {
                //Logger.Error("Login user error:" + string.Format("Server:{0},UserName:{1},Pwd:{2}", Domain, UserName, Password), ex);
            }
        }
#else
        LoginUser loginUser;

        
        public string UserName
        {
            get
            {
                return loginUser.LoginId;
            }
        }


        public string Password
        {
            get
            {
                return EncryptTool.Decrypt(loginUser.Pwd);
            }
        }

        protected override void OnInit(EventArgs e)
        {
            try
            {
                //string currentUser = Request.RequestType == "POST"
                //? GetCurrentUserCookie()
                //: Authentication.GetCurrentUser();
                string currentUser = Authentication.GetCurrentUser();

                if (string.IsNullOrEmpty(currentUser))
                {
                    string logonUrl = Authentication.GetLogonUrl();
                    Response.Redirect(logonUrl);
                }
                
                loginUser = new LoginUser(currentUser);

                if (!WindowsContext.Instance.ImpersonateValidUser(UserName, Domain, Password))
                {
                    lblMessage.Text = "no user";
                }
                else
                {
                    //UploadContext.InitUserName(currentUser);
                    lblMessage.Text = WindowsIdentity.GetCurrent().Name;
                    ADEntry adEntry = new ADEntry(UserName, Password);
                    userProfile = adEntry.UserProfile;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Login user error:" + string.Format("Server:{0},UserName:{1},Pwd:{2}", Domain, UserName, Password), ex);
            }
        }
#endif
        private void SaveFiles()
        {
            for (int i = 0; i < Request.Files.Count; i++)
            {
                HttpPostedFile file = Request.Files[i];
                if (null == file || file.ContentLength == 0)
                {
                    return;
                }

                string filename = Path.GetFileName(file.FileName);
                string fullFilename = Path.Combine(CurrentPath, filename);

                file.SaveAs(fullFilename);
            }
        }

        private List<WebApp.Code.FileManager> GetRootDrives()
        {
            var query = from p in userProfile.NetDrives
                        select new WebApp.Code.FileManager()
                        {
                            FileType = FileType.Folder,
                            Name = p.DriveName
                        };
            return query.ToList();
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            //if (Page.Request.HttpMethod.ToUpper() == "POST")
            //{
            //    SaveFiles();
            //    return;
            //}

            InitScript();

            if (!Page.IsPostBack)
            {
                rptItem.DataSource = GetRootDrives();
                rptItem.DataBind();
                txtCurrentPath.Text = string.Empty;
                txtFileName.Text = string.Empty;

            }
        }

        public void InitScript()
        {
            string cbScript =
                Page.ClientScript.GetCallbackEventReference(this, "arg", "OpenFolder", "context", "clientErrorCallback", false);
            string functionScript = @"function CallServer(arg,context,clientErrorCallback){" + cbScript + "}";

            Page.ClientScript.RegisterStartupScript(this.GetType(), "callServer", functionScript, true);

            string pbScript = Page.ClientScript.GetPostBackEventReference(new PostBackOptions(this, "arg")).Replace("'arg'", "arg");

            string pbFunction = @"function downloadPostBack(arg){" + pbScript + "}";
            Page.ClientScript.RegisterStartupScript(this.GetType(), "downloadPostBack", pbFunction, true);
        }


        private string JSONStringFilter(string json)
        {
            return json.Replace("\\", "\\\\").Replace("\n", "");
        }
        private string GetFileListJson(List<WebApp.Code.FileManager> fileList)
        {
            List<string> list = new List<string>();
            foreach (var p in fileList)
            {
                list.Add("{" + string.Format("\"fileType\":\"{0}\",\"name\":\"{1}\"", p.FileType, p.Name) + "}");
            }

            string path = string.Empty;
            if (CurrentDrive != null)
            {
                path = CurrentPath.Replace(CurrentDrive.DrivePath, CurrentDrive.DriveName).Replace("\\", "\\\\");
            }

            return "{"
                + string.Format("\"result\":{0},\"path\":\"{1}\",\"data\":[{2}] "
                , "true", path, string.Join(",", list.ToArray()))
                + "}";
        }
        public string GetCallbackResult()
        {
            string result = "{}";
            try
            {
                if (callbackEvent == EventName.Home)
                {

                    result = GetFileListJson(GetRootDrives());
                }
                else if (callbackEvent == EventName.FolderView
                    || callbackEvent == EventName.Refresh
                    || callbackEvent == EventName.Delete)
                {
                    FolderManager folder = new FolderManager(CurrentPath);

                    result = GetFileListJson(folder.Files);
                }
            }
            catch (Exception ex)
            {
                result = "{"
                        + string.Format("\"result\":{0},\"path\":\"{1}\",\"data\":\"{2}\" "
                        , "false", "", JSONStringFilter(ex.Message))
                        + "}";
            }

            return result;
        }

        public void RaiseCallbackEvent(string eventArgument)
        {
            string[] arg = eventArgument.Split('|');

            callbackEvent = (EventName)Enum.Parse(typeof(EventName), arg[0]);

            switch (callbackEvent)
            {
                case EventName.Home:
                    Home();
                    break;
                case EventName.Refresh:
                case EventName.FolderView:
                    FolderView(arg[1]);
                    break;
                case EventName.Delete:
                    FileDelete(arg[1], arg[2]);
                    break;
                case EventName.Download:
                    break;
                default:
                    break;
            }


        }
        public void FolderView(string fullPath)
        {
            CurrentPath = RevertToPhysicalPath(fullPath);


        }
        public void Home()
        {
            CurrentPath = string.Empty;
            CurrentDrive = null;
        }

        public void FileDelete(string virtualPath, string filesString)
        {
            string phsicalPath = RevertToPhysicalPath(virtualPath);
            string[] files = filesString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var fileName in files)
            {
                string fullFileName = phsicalPath + "\\" + fileName;
                if (File.Exists(fullFileName))
                {
                    File.Delete(fullFileName);
                }
            }
        }


        protected void MultiFilesDownload()
        {
            string path = RevertToPhysicalPath(txtCurrentPath.Text);
            string[] files = txtFileName.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            if (files.Count() == 1)
            {
                string fullFileName = path + "\\" + files[0];
                SingleFileDownload(fullFileName);
            }
            else if (files.Count() > 1)
            {
                DownloadZipFile(path, files);
            }
            //HttpContext.Current.ApplicationInstance.CompleteRequest();

        }

        protected void SingleFileDownload(string fullFileName)
        {
            if (File.Exists(fullFileName))
            {
                string fileName = Server.UrlDecode(Path.GetFileName(fullFileName));
                Page.Response.Clear();
                Page.Response.ContentType = "application/octet-stream";
                Page.Response.AddHeader("Content-Disposition",
                                        "attachment;filename=" + fileName);
                //Page.Response.TransmitFile(file);
                //Page.Response.WriteFile(file);
                byte[] buffer = File.ReadAllBytes(fullFileName);
                Page.Response.BinaryWrite(buffer);
                Page.Response.End();
            }
        }

        protected void DownloadZipFile(string path, string[] files)
        {
            Response.Clear();
            //Response.BufferOutput = false;  // for large files
            string filename = "files.zip";
            //Response.ContentType = "application/zip";
            Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
            Response.ContentType = "application/x-zip-compressed";

            using (Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile())
            {
                foreach (string fileName in files)
                {
                    string fullFileName = path + "\\" + fileName;
                    if (File.Exists(fullFileName))
                    {
                        zipFile.AddFile(fullFileName, "");
                    }
                }
                zipFile.Save(Response.OutputStream);
            }
            Response.End();
        }

        protected string RevertToPhysicalPath(string virtualPath)
        {
            string driveName = virtualPath.Trim().Substring(0, 1);
            foreach (var item in userProfile.NetDrives)
            {
                if (driveName == item.DriveName)
                {
                    CurrentDrive = item;

                    string realPath = virtualPath.Remove(0, 1);

                    return item.DrivePath + realPath;
                }
            }
            return string.Empty;
        }



        public void RaisePostBackEvent(string eventArgument)
        {
            if (string.IsNullOrEmpty(eventArgument))
            {
                MultiFilesDownload();
            }
            else
            {
                string path = RevertToPhysicalPath(txtCurrentPath.Text);
                string fullFileName = path + "\\" + eventArgument;

                SingleFileDownload(fullFileName);
            }
        }
    }

    public enum EventName { Home, Refresh, FolderView, Delete, Download }
}